3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2019 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
14 * Gestion de l'installation des plugins
16 * @package SPIP\Core\Plugins
20 if (!defined('_ECRIRE_INC_VERSION')) {
25 * Installe ou retire un plugin
27 * Permet d'installer ou retirer un plugin en incluant les fichiers
28 * associés et en lançant les fonctions spécifiques.
30 * 1. d'abord sur l'argument `test`,
31 * 2. ensuite sur l'action demandée si le test repond `false`
32 * 3. enfin sur l'argument `test` à nouveau.
34 * L'index `install_test` du tableau résultat est un tableau formé :
37 * - des echo de l'étape 2
40 * La fonction quitte (retourne false) si le plugin
41 * n'a pas de version d'installation définie
42 * (information `version_base` dans le paquet.xml)
46 * @param string $action
47 * Nom de l'action (install|uninstall)
48 * @param string $dir_type
49 * Répertoire du plugin
51 * - False si le plugin n'a pas d'installation,
52 * - true si déjà installé,
53 * - le tableau de get_infos sinon
55 function plugins_installer_dist($plug, $action, $dir_type = '_DIR_PLUGINS') {
56 $get_infos = charger_fonction('get_infos', 'plugins');
57 $infos = $get_infos($plug, false, constant($dir_type));
58 if (!isset($infos['install']) or !$infos['install']) {
61 // passer en chemin absolu si possible, c'est plus efficace
62 $dir = str_replace('_DIR_', '_ROOT_', $dir_type);
66 $dir = constant($dir);
67 foreach ($infos['install'] as $file) {
68 $file = $dir . $plug . "/" . trim($file);
69 if (file_exists($file)) {
73 $version = isset($infos['schema']) ?
$infos['schema'] : '';
75 $f = $infos['prefix'] . "_install";
76 if (!function_exists($f)) {
77 $f = isset($infos['schema']) ?
'spip_plugin_install' : '';
79 $arg = $infos['prefix'];
80 } // stupide: info deja dans le nom
83 // installation sans operation particuliere
84 $infos['install_test'] = array(true, '');
88 $test = $f('test', $arg, $version);
89 if ($action == 'uninstall') {
92 // Si deja fait, on ne dit rien
96 // Si install et que l'on a la meta d'installation, c'est un upgrade
97 if ($action == 'install' && !is_null(lire_meta($infos['prefix'] . '_base_version'))) {
98 $infos['upgrade'] = true;
101 // executer l'installation ou l'inverse
102 // et renvoyer la trace (mais il faudrait passer en AJAX plutot)
104 $f($action, $arg, $version);
105 $aff = ob_get_contents();
107 // vider le cache des descriptions de tables a chaque (de)installation
108 $trouver_table = charger_fonction('trouver_table', 'base');
110 $infos['install_test'] = array($f('test', $arg, $version), $aff);
115 // Fonction par defaut pour install/desinstall
117 // http://code.spip.net/@spip_plugin_install
118 function spip_plugin_install($action, $infos, $version_cible) {
119 $prefix = $infos['prefix'];
120 if (isset($infos['meta']) and (($table = $infos['meta']) !== 'meta')) {
121 $nom_meta = "base_version";
123 $nom_meta = $prefix . "_base_version";
128 return (isset($GLOBALS[$table])
129 and isset($GLOBALS[$table][$nom_meta])
130 and spip_version_compare($GLOBALS[$table][$nom_meta], $version_cible, '>='));
133 if (function_exists($upgrade = $prefix . "_upgrade")) {
134 $upgrade($nom_meta, $version_cible, $table);
138 if (function_exists($vider_tables = $prefix . "_vider_tables")) {
139 $vider_tables($nom_meta, $table);
147 * Compare 2 numéros de version entre elles.
149 * Cette fonction est identique (arguments et retours) a la fonction PHP
150 * version_compare() qu'elle appelle. Cependant, cette fonction reformate
151 * les numeros de versions pour ameliorer certains usages dans SPIP ou bugs
152 * dans PHP. On permet ainsi de comparer 3.0.4 à 3.0.* par exemple.
155 * Numero de version servant de base a la comparaison.
156 * Ce numero ne peut pas comporter d'etoile.
158 * Numero de version a comparer.
159 * Il peut posseder des etoiles tel que 3.0.*
161 * Un operateur eventuel (<, >, <=, >=, =, == ...)
163 * Sans operateur : int. -1 pour inferieur, 0 pour egal, 1 pour superieur
164 * Avec operateur : bool.
166 function spip_version_compare($v1, $v2, $op = null) {
167 $v1 = strtolower(preg_replace(',([0-9])[\s.-]?(dev|alpha|a|beta|b|rc|pl|p),i', '\\1.\\2', $v1));
168 $v2 = strtolower(preg_replace(',([0-9])[\s.-]?(dev|alpha|a|beta|b|rc|pl|p),i', '\\1.\\2', $v2));
169 $v1 = str_replace('rc', 'RC', $v1); // certaines versions de PHP ne comprennent RC qu'en majuscule
170 $v2 = str_replace('rc', 'RC', $v2); // certaines versions de PHP ne comprennent RC qu'en majuscule
172 $v1 = explode('.', $v1);
173 $v2 = explode('.', $v2);
174 // $v1 est toujours une version, donc sans etoile
175 while (count($v1) < count($v2)) {
179 // $v2 peut etre une borne, donc accepte l'etoile
181 foreach ($v1 as $k => $v) {
182 if (!isset($v2[$k])) {
183 $v2[] = ($etoile and (is_numeric($v) or $v == 'pl' or $v == 'p')) ?
$v : '0';
185 if ($v2[$k] == '*') {
191 $v1 = implode('.', $v1);
192 $v2 = implode('.', $v2);
194 return $op ?
version_compare($v1, $v2, $op) : version_compare($v1, $v2);
199 * Retourne un tableau des plugins activés sur le site
201 * Retourne la meta `plugin` désérialisée.
202 * Chaque élément du tableau est lui-même un tableau contenant
203 * les détails du plugin en question : répertoire et version.
206 * Si le contenu de la meta n’est pas un tableau, cette fonction transforme
207 * l’ancien format en tableau sérialisé pour être conforme au nouveau fonctionnement (SPIP >= 1.9.2)
209 * @return array Tableau des plugins actifs
211 function liste_plugin_actifs() {
212 $liste = isset($GLOBALS['meta']['plugin']) ?
$GLOBALS['meta']['plugin'] : '';
216 if (!is_array($liste = unserialize($liste))) {
217 // compatibilite pre 1.9.2, mettre a jour la meta
218 spip_log("MAJ meta plugin vieille version : $liste", "plugin");
220 list(, $liste) = liste_plugin_valides(explode(",", $liste));
223 // compat au moment d'une migration depuis version anterieure
224 // si pas de dir_type, alors c'est _DIR_PLUGINS
225 foreach ($liste as $prefix => $infos) {
226 if (!isset($infos['dir_type'])) {
227 $liste[$prefix]['dir_type'] = "_DIR_PLUGINS";
233 ecrire_meta('plugin', serialize($liste));